package com.zretc.controller;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;

import org.apache.commons.codec.digest.DigestUtils;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.zretc.entity.UserInfo;
import com.zretc.service.UserService;
import com.zretc.service.impl.UserServiceImpl;

/**
 * Servlet implementation class RegisterAndLoginServlet
 */
@WebServlet("/RegisterAndLoginServlet")
@MultipartConfig
public class RegisterAndLoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private UserService userService = new UserServiceImpl();

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public RegisterAndLoginServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 获取op的参数
		String op = request.getParameter("op");
		if ("existsOfuserName".equals(op)) {
			// 判断用户名是否存在
			doExistsOfUserName(request, response);
		} else if ("register".equals(op)) {
			// 注册
			doRegister(request, response);
		} else if ("login".equals(op)) {
			// 登录
			doLogin(request, response);
		} else if ("sendVerifyCode".equals(op)) {
			// 发送验证码
			doSendVerifyCode(request, response);
		} else if ("checkCode".equals(op)) {
			// 验证登录验证码
			doCheckLoginCode(request, response);
		} else if ("verifyCode".equals(op)) {
			// 验证手机短信验证码
			doVerifyRegisterCode(request, response);
		}

	}

	private void doVerifyRegisterCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 获取输入的验证码
		String verifyCode = request.getParameter("verifyCode");
		// 获取手机验证码
		String randomCode = (String) request.getSession().getAttribute("randomCode");

		// 判断输入的验证码是否和手机验证码相同
		if (randomCode.equals(verifyCode)) {
			// 响应数据
			response.getWriter().write("true");
		} else {
			// 响应数据
			response.getWriter().write("false");
		}
	}

	private void doCheckLoginCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 获取验证码
		String code = request.getParameter("code");
		// 验证验证码
		String sessionCode = request.getSession().getAttribute("code").toString();
		if (code != null && !"".equals(code) && sessionCode != null && !"".equals(sessionCode)) {
			if (code.equalsIgnoreCase(sessionCode)) {
				response.getWriter().write("true");
			} else {
				response.getWriter().write("false");
			}

		} else {
			response.getWriter().write("false");
		}

	}

	private void doSendVerifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 生成一个四位数的随机验证码
		String str = ""; // 0123456789
		for (int i = 0; i < 4; i++) {
			str += (int) Math.floor(Math.random() * 10);
		}

		// 将短信验证码存储到session中
		request.getSession().setAttribute("randomCode", str);
		// 获取手机号码
		String userPhone = request.getParameter("userPhone");
		// 获取前端验证码
		// String code = request.getParameter("verifyCode");

		// 调用方法--发送验证码
		boolean sendCode = sendCode(userPhone, str);
		// 响应数据
		response.getWriter().write(sendCode + "");

	}

	private boolean sendCode(String userPhone, String str) {
		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI4G1Q8SwaEMs3BEbY1s65",
				"HItF5h7JMJIn6KvFG5lZ4lWfjUeUKX");
		IAcsClient client = new DefaultAcsClient(profile);

		CommonRequest request = new CommonRequest();
		request.setMethod(MethodType.POST);
		request.setDomain("dysmsapi.aliyuncs.com");
		request.setVersion("2017-05-25");
		request.setAction("SendSms");
		request.putQueryParameter("RegionId", "cn-hangzhou");
		request.putQueryParameter("PhoneNumbers", userPhone);
		request.putQueryParameter("SignName", "冬天去哪里民宿");
		request.putQueryParameter("TemplateCode", "SMS_193233817");
		request.putQueryParameter("TemplateParam", "{'code':'" + str + "'}");
		try {
			CommonResponse response = client.getCommonResponse(request);
			System.out.println(response.getData());
		} catch (ServerException e) {
			e.printStackTrace();
		} catch (ClientException e) {
			e.printStackTrace();
		}
		return true;

	}

	private void doLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {

		response.setCharacterEncoding("UTF-8");
		// 获取用户名
		String userName = request.getParameter("userName");
		// 获取密码
		String pswd = request.getParameter("userPwd");
		// 对密码进行加密，加密后再通过Hibernate往数据库里存
		String userPassword = DigestUtils.md5Hex(pswd);

		// 调用业务层逻辑
		UserInfo user = userService.login(userName, userPassword);

		if (user != null) {
			// 登录成功
			// 用户信息存储在session会话作用域中
			HttpSession session = request.getSession();
			session.setAttribute("user", user);

			// 获取复选框组件的值
			String rememberPassword = request.getParameter("rememberPassword");

			// 用户选择记住密码
			if (rememberPassword != null && "rememberPassword".equals(rememberPassword)) {

				// 多用户
				// Cookie cookie = new Cookie(userName, userPassword);
				Cookie cookie = new Cookie(userName, pswd);
				// 设置cookie的有效时间
				cookie.setMaxAge(60 * 20);
				// 将cookie对象添加到HTTP响应头中
				response.addCookie(cookie);

			} else {

				// 多用户
				Cookie[] cookies = request.getCookies();
				Cookie cookie = null;
				for (int i = 0; i < cookies.length; i++) {
					cookie = cookies[i];
					if (cookie.getName().equals(userName)) {
						cookie.setMaxAge(0);
						response.addCookie(cookie);
					}
				}
			}

			// 重定向到首页
			response.sendRedirect("front/index.jsp");
		} else {
			// 登录失败
			// 重定向到登录页面
			response.sendRedirect("front/login.jsp?loginErrorMessage=error");
		}

	}

	private void doRegister(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		// 获取用户名
		String userName = request.getParameter("userName");
		// 获取用户密码
		String userPwd = request.getParameter("userPwd");
		// 对密码进行加密，加密后再通过Hibernate往数据库里存
		String userPassword = DigestUtils.md5Hex(userPwd);
		// 获取用户手机号
		String userPhone = request.getParameter("userPhone");

		// 获取性别
		String userSex = request.getParameter("userSex");
		
		// 接收文件组件
		Part part = request.getPart("userPicture");

		// 初始为空
		UserInfo userInfo = null;
		// 判断是否上传文件

		// 没上传
		if (part.getSize() == 0) {
			userInfo = new UserInfo(0, userName, userPassword, userSex, userPhone, null);
		} else { // 有上传
			// 允许的文件图片类型
			String allowImgType = "image/jpg,image/jpeg,image/png";
			// 允许的文件图片类型集合
			List<String> allowImgTypeList = Arrays.asList(allowImgType.split(","));

			// 判断上传的文件类型是否合法
			String contentType = part.getContentType(); // 获取上传文件的MIME类型

			// 判断上传的文件MIME类型是否在指定的允许类型集合
			if (allowImgTypeList.contains(contentType) == false) {
				System.out.println("文件类型不匹配!");
				// 重定向注册页面,提示文件不合法
				response.sendRedirect("front/register.jsp?fileuploaderror=fileuploaderror");
				return;
			} else {
				// 获取文件真实名:Servlet 3.0不提供获取上传文件名的方法,通过请求头信息间接获取
				String header = part.getHeader("content-disposition");
				String realName = header.substring(header.indexOf("filename=") + 10, header.length() - 1);
				// 获取真实文件名的后缀
				String fileSuffix = realName.substring(realName.lastIndexOf("."));
				// 使用时间戳+随机数自动生成文件名,避免文件名重复问题
				// JDK1.8 日期时间类
				LocalDateTime now = LocalDateTime.now();
				DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddhhmmssSSS");
				// 将当前日期时间转成字符串
				String formatDate = ofPattern.format(now);
				// 随机数
				int random = (int) (Math.random() * 1000 + 1);
				// 拼接
				StringBuffer fileName = new StringBuffer();
				fileName.append(formatDate).append(random);

				// 将文件存储在指定服务器中(本地电脑E盘)
				File file = new File("C:\\image");
				if (!file.exists()) {
					// 创建目录
					file.mkdirs();
				}

				// 将文件写入指定位置
				String filePath = file.getPath() + File.separator + fileName + fileSuffix; // E:\fileupload\images\1.jpg
				part.write(filePath);

				// 调用业务层
				// 数据库中仅需要存储文件名.扩展名---fileName + fileSuffix = userPicture
				userInfo = new UserInfo(0, userName, userPassword, userSex, userPhone, fileName + fileSuffix);
				/* userService.register(userInfo); */
			}

		}

		userService.register(userInfo);
		// 重定向到前台首页
		response.sendRedirect("front/login.jsp");

	}

	private void doExistsOfUserName(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 调度
		// 业务逻辑层
		String userName = request.getParameter("userName");
		Boolean existsOfUserName = userService.existsOfUserName(userName);
		// 响应数据
		response.getWriter().write(existsOfUserName + "");
	}

}
